package com.xgj.service.impl;

import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xgj.dao.*;
import com.xgj.dto.ImportResult;
import com.xgj.entity.*;
import com.xgj.enums.ErrorCode;
import com.xgj.exception.DataImportException;
import com.xgj.service.RandomUserService;
import com.xgj.utils.HttpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

@Service
public class RandomUserServiceImpl implements RandomUserService {

    @Autowired
    private NameDao nameDao;
    @Autowired
    private LoginDao loginDao;
    @Autowired
    private PictureDao pictureDao;
    @Autowired
    private RandomUserDao randomUserDao;
    @Autowired
    private Snowflake snowflake;

    @Value("${id.generator.type:snowflake}") // 从配置读取ID生成策略,uuid或者雪花算法
    private String idGeneratorType;

    //为了测试部分成功：模拟收到3条数据，第一条成功，第二条仔插入login表报错的
    // 假设这里有一个静态变量来记录当前处理的数据序号，无法写到方法中
    // 用于记录当前处理的数据序号
    private int dataIndex = 0;

    @Override
    //改成每条数据一个事务，每条数据插入4张表
    public ImportResult importRandomUsers() {
        dataIndex = 0;//每次调用接口都归0

        //失败记录合集
        List<ImportResult.FailedRecord> failedRecords = new ArrayList<>();
        int total = 0;
        int success = 0;
        int failed = 0;

        // 调用外部接口
        String url = "https://randomuser.me/api/?results=3";
        String response = null;
        try {
            response = HttpUtil.get(url, null);
        } catch (Exception e) {
            // 全局性错误1：调用外部接口失败，直接抛出异常
            //抛出来会被Controller来处理
            DataImportException dataImportException = new DataImportException(ErrorCode.HTTP_ERROR, e);
            dataImportException.printStackTrace();
            throw dataImportException;//调用外部接口失败，不需要构建ImportResult返回
        }

        // 解析数据
        JSONArray results = null;
        try {
            results = JSON.parseObject(response).getJSONArray("results");
        } catch (Exception e) {
            // 全局性错误2：JSON 解析失败，直接抛出异常
            throw new DataImportException(ErrorCode.JSON_PARSE_ERROR, e);//JSON 解析失败，不需要构建ImportResult返回
        }

        total = results.size();

        // 处理每条数据
        //这里应该每条数据会插入4张表，每插入一条数据当做一个事物
        for (int i = 0; i < results.size(); i++) {
            JSONObject userJson = results.getJSONObject(i);
            try {
                RandomUser randomUser = parseUser(userJson);
                // 开启每条数据的事务处理
                processSingleUserTransaction(randomUser);
                success++;
            } /*catch (Exception e) { //保存表saveLogin报错会被这里获取到
                failed++;
                //failedRecords 是失败记录的list
                failedRecords.add(createFailedRecord(i + 1, userJson, e));
            }*/catch (DataImportException e) {
                failed++;
                // 获取异常中的错误码、表名等信息
                ErrorCode errorCode = e.getErrorCode();
                String tableName = e.getTableName();
                String errorDetail = e.getMessage();
                String errorMsg = errorCode.getMessage();
                if (tableName != null) {
                    errorMsg = errorMsg.replace("{tableName}", tableName);
                }
                // 创建失败记录
                failedRecords.add(new ImportResult.FailedRecord(
                        i+1,
                        maskSensitiveData(userJson),//数据脱敏
                        errorCode.getCode(),
                        errorDetail,
                        errorDetail   //给开发者看的报错信息
                ));
            } catch (Exception e) {
                failed++;
                // 处理其他未知异常
                ErrorCode errorCode = ErrorCode.UNKNOWN_ERROR;
                failedRecords.add(new ImportResult.FailedRecord(
                        i+1,
                        maskSensitiveData(userJson),
                        errorCode.getCode(),
                        errorCode.getMessage(),
                        e.getMessage()
                ));
            }
        }

        return new ImportResult(total, success, failed, failedRecords);
    }

    // 解析JSON到实体对象
    private RandomUser parseUser(JSONObject userJson) {
        return new RandomUser(
                userJson.getString("gender"),
                userJson.getString("email"),
                userJson.getString("phone"),
                userJson.getString("nat"),
                parseName(userJson.getJSONObject("name")),
                parseLogin(userJson.getJSONObject("login")),
                parsePicture(userJson.getJSONObject("picture"))
        );
    }

    // ID生成策略
    private void generateAndSetId(RandomUser user) {
        //yml中配置生成ID策略
        if ("uuid".equalsIgnoreCase(idGeneratorType)) {
//            user.setId(UUID.randomUUID().toString());
        } else { // 默认用雪花算法
//            user.setId(snowflake.nextId());
        }
    }

    // 处理单条用户数据的事务
    @Transactional
    void processSingleUserTransaction(RandomUser user) {
        // 保存关联表数据
        saveName(user.getName());
        saveLogin(user.getLogin());
        savePicture(user.getPicture());

            // 设置外键ID（假设关联表使用自增ID）
        user.setNameId(user.getName().getId());
        user.setLoginId(user.getLogin().getId());
        user.setPictureId(user.getPicture().getId());

        // 保存主表
        saveRandomUser(user);
    }

    // 保存Name表数据
    @Transactional
    void saveName(Name name) {
        try {
            nameDao.insert(name);
        } catch (Exception e) {
            throw new DataImportException(ErrorCode.DATABASE_TABLE_SAVE_ERROR, "Name", e);
        }
    }

    // 保存Login表数据
    @Transactional
    void saveLogin(Login login) {
        dataIndex++;
        // 模拟第二条数据插入Login表报错
        if (dataIndex == 2) {
            throw new DataImportException(ErrorCode.DATABASE_TABLE_SAVE_ERROR, "Login", new RuntimeException("模拟 Login 表插入失败"));
        }
        try {
            loginDao.insert(login);
        } catch (Exception e) {
            throw new DataImportException(ErrorCode.DATABASE_TABLE_SAVE_ERROR, "Login", e);
        }
    }

    // 保存Picture表数据
    @Transactional
    void savePicture(Picture picture) {
        try {
            pictureDao.insert(picture);
        } catch (Exception e) {
            throw new DataImportException(ErrorCode.DATABASE_TABLE_SAVE_ERROR, "Picture", e);
        }
    }

    // 保存RandomUser表数据
    @Transactional
    void saveRandomUser(RandomUser randomUser) {
        try {
            randomUserDao.insert(randomUser);
        } catch (Exception e) {
            throw new DataImportException(ErrorCode.DATABASE_TABLE_SAVE_ERROR, "RandomUser", e);
        }
    }

    // 创建失败记录
    private ImportResult.FailedRecord createFailedRecord(int index,
                                                         JSONObject data,
                                                         Exception e) {
        ErrorCode errorCode = getErrorCodeFromException(e);
        return new ImportResult.FailedRecord(
                index,
                maskSensitiveData(data), // 数据脱敏
                errorCode.getCode(),
                errorCode.getMessage(),
                e.getMessage() // 详细错误信息（开发者调试用）
        );
    }

    //根据错误来判断是枚举的哪个错误
    private ErrorCode getErrorCodeFromException(Exception e) {
        String errorMessage = e.getMessage();
        if (errorMessage != null) {
            if (errorMessage.contains("JSON 解析失败")) {
                return ErrorCode.JSON_PARSE_ERROR;
            } else if (errorMessage.contains("邮箱格式无效")) {
                return ErrorCode.EMAIL_FORMAT_ERROR;
            } else if (errorMessage.contains("电话号码格式无效")) {
                return ErrorCode.PHONE_FORMAT_ERROR;
            } else if (errorMessage.contains("性别格式无效")) {
                return ErrorCode.GENDER_FORMAT_ERROR;
            } else if (errorMessage.contains("数据库连接失败")) {
                return ErrorCode.DB_CONNECTION_ERROR;
            } else if (errorMessage.contains("数据库约束冲突")) {
                return ErrorCode.DB_CONSTRAINT_VIOLATION;
            } else if (errorMessage.contains("主键或唯一键冲突")) {
                return ErrorCode.DB_DUPLICATE_KEY;
            } else if (errorMessage.contains("数据库操作超时")) {
                return ErrorCode.DB_TIMEOUT;
            } else if (errorMessage.contains("保存失败")) {
                return ErrorCode.DATABASE_TABLE_SAVE_ERROR;
            }
        }
        return ErrorCode.UNKNOWN_ERROR;
    }


    // 数据脱敏处理
    private String maskSensitiveData(JSONObject data) {
        JSONObject masked = new JSONObject(data);
        // 邮箱脱敏
        if (masked.containsKey("email")) {
            String email = masked.getString("email");
            masked.put("email", email.replaceAll("(\\w{2})\\w+@", "$1***@"));
        }
        // 电话脱敏
        if (masked.containsKey("phone")) {
            String phone = masked.getString("phone");
            masked.put("phone", phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
        }
        return masked.toJSONString();
    }

    // 嵌套对象解析方法
    private Name parseName(JSONObject nameJson) {
        return new Name(
                nameJson.getString("title"),
                nameJson.getString("first"),
                nameJson.getString("last")
        );
    }

    private Login parseLogin(JSONObject loginJson) {
        return new Login(
                loginJson.getString("uuid"),
                loginJson.getString("username"),
                loginJson.getString("password"),
                loginJson.getString("salt"),
                loginJson.getString("md5"),
                loginJson.getString("sha1"),
                loginJson.getString("sha256")
        );
    }

    private Picture parsePicture(JSONObject pictureJson) {
        return new Picture(
                pictureJson.getString("large"),
                pictureJson.getString("medium"),
                pictureJson.getString("thumbnail")
        );
    }
}
